package com.qf.springcloud.controller;

import com.netflix.appinfo.InstanceInfo;
import com.netflix.discovery.EurekaClient;
import com.netflix.hystrix.contrib.javanica.annotation.HystrixCommand;
import com.netflix.hystrix.contrib.javanica.annotation.HystrixProperty;
import com.qf.springcloud.client.ProducerClient;
import com.qf.springcloud.client.PythonClient;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.cloud.context.config.annotation.RefreshScope;
import org.springframework.util.StringUtils;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.client.RestTemplate;

import javax.annotation.Resource;
import java.util.Map;

@RestController
@RequestMapping("/consumer")
@RefreshScope
public class ConsumerController {

    @Autowired
    private RestTemplate restTemplate;

    @Resource
    private EurekaClient eurekaClient;

    @Resource
    private ProducerClient producerClient;

    @Resource
    private PythonClient pythonClient;

    @GetMapping("/python")
    public String python(){
        return pythonClient.python();
    }

    @Value("${version}")
    private String version;

    @GetMapping("/version")
    public String version(){
        return version;
    }


    @GetMapping("/test")
    public String test(){
        /*
        //1. 从eureka上获取PRODUCER服务信息
        InstanceInfo producer = eurekaClient.getNextServerFromEureka("PRODUCER", false);
        //2. 获取PRODUCER的ip和port
        String ip = producer.getIPAddr();
        int port = producer.getPort();
        //3. 调用PRODUCER的服务
        String result = restTemplate.getForObject("http://"+ip+":"+port+"/producer/test", String.class);
*/
        /*
        //2. 通过Ribbon实现负载均衡并调用指定服务接口，路径使用服务名称，Ribbon可以解析成当前服务的ip和port
        String result = restTemplate.getForObject("http://PRODUCER/producer/test", String.class);
        */
        String result = producerClient.test();
        return result;
    }


    @Value("${spring.application.name}")
    public String appName;

    @GetMapping("/test1/{id}")
    public String test1(@PathVariable String id) throws InterruptedException {
        if("123".equalsIgnoreCase(id)){
            int i = 1 / 0;
        }else if("456".equalsIgnoreCase(id)){
            Thread.sleep(2000);
        }
        System.out.println("test1:" + Thread.currentThread().getName());
        String result = producerClient.test1(id);
        return result + "..." +appName;
    }





    @GetMapping("/test2")
    @HystrixCommand(fallbackMethod = "test2Fallback",
                    commandProperties = {    // sentinel
                        @HystrixProperty(name = "execution.isolation.strategy",value = "SEMAPHORE"),
                        @HystrixProperty(name = "execution.isolation.thread.timeoutInMilliseconds",value = "500"),
                        @HystrixProperty(name = "execution.timeout.enabled",value = "false"),
                        @HystrixProperty(name = "circuitBreaker.enabled",value = "true"),
                        @HystrixProperty(name = "circuitBreaker.requestVolumeThreshold",value = "5"),
                        @HystrixProperty(name = "circuitBreaker.sleepWindowInMilliseconds",value = "30000"),
                        @HystrixProperty(name = "circuitBreaker.errorThresholdPercentage",value = "50"),
                    })
    public String test2(String name,Integer age) throws InterruptedException {
        System.out.println("test2:" + Thread.currentThread().getName());
        // name为必传项
        if(StringUtils.isEmpty(name)){
            throw new RuntimeException();
        }
        // 当前代码需要执行1.5s
//        Thread.sleep(1300);
        String result = producerClient.test2(name,age);
        return result;
    }

    // 时test2的降级方法
    public String test2Fallback(String name,Integer age){
        return "test2 is fail , my name is down level method!!";
    }








    @PostMapping("/test3")
    public String test3(@RequestBody Map map){
        String result = producerClient.test3(map);
        return result;
    }





}
